#pragma once

#include <functional>
#include "socket.hpp"
#include "log.hpp"
#include "Inetaddr.hpp"

using namespace log_namespace;
using namespace socket_namespace;

using task_t = std::function<void()>;

using command_service_t = std::function<void(int socketfd, inetAddr addr)>;

const static int gport = 8888;

using service_t = std::function<void(socketPtr, const inetAddr&)>;

class tcpServer
{    
public:
    tcpServer(service_t service, uint16_t port = gport)
        :_port(gport)
        ,_listensock(std::make_shared<TCPSocket>())
        ,_isrunning(false)
        ,_service(service)
    {
        _listensock->buildListenSocket(port);
    }

    // version 2: 多线程版本
    class threadData
    {
    public:
        threadData(socketPtr socketfd, tcpServer *tcS, inetAddr addr)
            :_ssocketfd(socketfd)
            ,_self(tcS)
            ,_addr(addr)
        {

        }
        socketPtr _ssocketfd;
        tcpServer *_self;
        inetAddr _addr;
    };

    static void *execute(void* args)
    {
        pthread_detach(pthread_self());
        threadData *td = static_cast<threadData *>(args);
        td->_self->_service(td->_ssocketfd, td->_addr);
        td->_ssocketfd->close();

        delete td;
        return nullptr;
    }
    
    // 子线程和主线程 共享一个 文件指针数组，所以不能通过随意关闭任意一个文件描述符
    void loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            inetAddr client;
            socketPtr newsock = _listensock->Accepter(&client);
            if (newsock == nullptr)
            {
                continue;
            }
            LOG(INFO, "get a new link, client info: %s\n, socketfd is: %d\n", client.addrStr().c_str(), newsock->getsockfd());

            pthread_t tid;
            threadData *td = new threadData(newsock, this, client);
            pthread_create(&tid, nullptr, execute, td);
        }
        _isrunning = false;
    }


    ~tcpServer()
    {

    }
private:
    uint16_t _port;
    socketPtr _listensock;
    bool _isrunning;
    service_t _service;
};


